#include "gd32f30x.h"
#include "string.h"
#include "stdint.h"
#include "stdio.h"
#include "DevicesCAN.h"


void vCan0Init(void)
{
    can_parameter_struct can_parameter = {0};
    can_filter_parameter_struct can_filter = {0};

    /* enable CAN clock */
    rcu_periph_clock_enable(RCU_CAN0);
    rcu_periph_clock_enable(RCU_GPIOD);

    /* configure CAN0 GPIO */
    gpio_init(GPIOD, GPIO_MODE_IPU, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);


    /* initialize CAN register */
    can_deinit(CAN0);

    can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
    /* initialize CAN parameters */
    can_parameter.time_triggered = DISABLE;
    can_parameter.auto_bus_off_recovery = DISABLE;
    can_parameter.auto_wake_up = DISABLE;
    can_parameter.auto_retrans = DISABLE;
    can_parameter.rec_fifo_overwrite = ENABLE;
    can_parameter.trans_fifo_order = ENABLE;
    can_parameter.working_mode = CAN_NORMAL_MODE;
    /* 波特率：PCLK1 / can_parameter.prescaler / (1 + can_parameter.time_segment_1 + can_parameter.time_segment_2) */
    can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
    can_parameter.time_segment_1 = CAN_BT_BS1_5TQ;
    can_parameter.time_segment_2 = CAN_BT_BS2_4TQ;
    can_parameter.prescaler = 6;
    /* initialize CAN */
    can_init(CAN0, &can_parameter);

    can_struct_para_init(CAN_INIT_STRUCT, &can_filter);
    /* initialize filter */ 
    can_filter.filter_number=0;
    can_filter.filter_mode = CAN_FILTERMODE_MASK;
    can_filter.filter_bits = CAN_FILTERBITS_32BIT;
    can_filter.filter_list_high = 0x0000;
    can_filter.filter_list_low = 0x0000;
    can_filter.filter_mask_high = 0x0000;
    can_filter.filter_mask_low = 0x0000;
    can_filter.filter_fifo_number = CAN_FIFO0;
    can_filter.filter_enable = ENABLE;
    can_filter_init(&can_filter);


    /* configure CAN0 NVIC */
    nvic_irq_enable(USBD_LP_CAN0_RX0_IRQn, 7, 0);
    /* enable can receive FIFO0 not empty interrupt */
    can_interrupt_enable(CAN0, CAN_INT_RFNE0);
}

int8_t cCanSendDatas(uint32_t can_periph, uint16_t usID, void *pvDatas, int32_t iLength)
{
    can_trasnmit_message_struct transmit_message = {0};
    int32_t iTimeOut = 0;
    uint8_t *pucDatas = pvDatas;
    int8_t cError = 0;

    if(pvDatas == NULL)
        return 1;

    /* initialize transmit message */
    transmit_message.tx_sfid = usID;
    transmit_message.tx_efid = 0;
    transmit_message.tx_ft = CAN_FT_DATA;
    transmit_message.tx_ff = CAN_FF_STANDARD;

    while(iLength > 0)
    {
        /* 计算当前帧传输长度 */
        transmit_message.tx_dlen = (iLength > 8) ? 8 : iLength;

        memcpy(transmit_message.tx_data, pucDatas, transmit_message.tx_dlen);

        pucDatas += transmit_message.tx_dlen;
        iLength  -= transmit_message.tx_dlen;

        /* 发送数据 */
        iTimeOut = 100000;
        while((can_message_transmit(can_periph, &transmit_message) == CAN_NOMAILBOX) && ((--iTimeOut) != 0));

        if(iTimeOut <= 0)
        {
            printf("cCanSendDatas error.\r\n");
            cError = 2;
            break;
        }
    }

    return cError;
}
